package com.yangfan.thread.thread_wangwenjun03;


import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @description: 消费者与生产者案例
 * @author: yangfan
 * @date: Created in 2020/1/26 0026 22:07
 * @modified By:
 *
 *
 * 面试题：sleep 与 wait 的区别
 *
 * 1.sleep 是 Thread 的方法  wait 是 Object 的方法
 * 2.sleep 不会释放锁，wait会释放锁
 * 3.wait 使用的时机必须在 同步锁 内或 同步块 内
 * 4.sleep 不需要 被唤醒  而 wait 则需要别人去唤醒它
 *
 */
public class TheadCommunicate3 {

    static class Supermarket {


        private Lock lock = new ReentrantLock();
        private Condition condition = lock.newCondition();//线程同步


        //当前货架上的商品数量
        private volatile int index = 1;

        //进货
        public void get() {

            try {

                lock.lock();

                //当前货物 如果 多余 货架数量
                while (index >= 10) {
                    //System.out.println("货架已经满了。。。");

                    /**
                     * condition.await()
                     * condition.wait();写错可。。。。导致一直有问题
                     */
                    condition.await();//进行等待

                }
                System.out.println(Thread.currentThread().getName() + ":线程进行生产：" + ++index);
                //通知消费者可以消费了
                condition.signal();
                //condition.signalAll();
                this.notifyAll();
            } catch (Exception e) {

            } finally {
                lock.unlock();
            }

        }


        //卖货
        public void set() {

            try {

                lock.lock();

                while (index <= 0) {

                    //System.out.println("货架已经没货了。。。");
                    condition.await();
                }

                System.out.println(Thread.currentThread().getName() + ":线程进行消费：" + --index);
                condition.signalAll();

                //condition.signalAll();
            } catch (Exception e) {

            } finally {
                lock.unlock();
            }

        }


    }


    static class Consumer extends Thread {

        Consumer(Supermarket supermarket,String name) {
            super(name);
            this.supermarket = supermarket;
        }

        private Supermarket supermarket;

        public void run() {
            while (true)
                supermarket.set();

        }

    }


    static class Producer extends Thread {

        @Override
        public void run() {
            while (true)
                supermarket.get();
        }

        Producer(Supermarket supermarket,String name) {
            super(name);
            this.supermarket = supermarket;
        }

        private Supermarket supermarket;

    }


    public static void main(String[] args) {

        Supermarket s = new Supermarket();//共享的

        new Consumer(s,"消费者1").start();
        new Consumer(s,"消费者2").start();
        new Consumer(s,"消费者3").start();
        new Consumer(s,"消费者4").start();

        new Producer(s,"生产者1").start();
        new Producer(s,"生产者2").start();


    }


}
